package com.eva.ss;

import com.eva.framework.rbac.service.LoginTokenService;
import com.eva.framework.rbac.session.SessionProperties;
import com.eva.ss.model.SsUserInfo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;

/**
 * 默认预认证过滤器，用于在进行认证之前填入用户信息（如果有）
 */
@Component
public class DefaultPreAuthFilter extends OncePerRequestFilter {

    @Resource
    private SessionProperties sessionProperties;

    @Resource
    private UserDetailsCache userDetailsCache;

    @Resource
    private LoginTokenService loginTokenService;

    @Override
    @SuppressWarnings("NullableProblems")
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {
        String token = loginTokenService.get(request);
        // 没有token，直接放行
        if (StringUtils.isBlank(token)) {
            filterChain.doFilter(request, response);
            return;
        }
        // 从缓存中获取用户信息
        SsUserInfo loginUserInfo = (SsUserInfo) userDetailsCache.get(token);
        // 如果存在登录信息，则将用户信息写入Security上下文
        if (loginUserInfo != null) {
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUserInfo, null, loginUserInfo.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            // 如果为交互式会话，则延长会话的过期时间
            if (SessionProperties.SessionMode.INTERACTIVE.equals(sessionProperties.getMode())) {
                userDetailsCache.relive(token);
            }
        }
        filterChain.doFilter(request, response);
    }
}
